import {
  Component,
  ViewChild,
  OnInit,
  ViewContainerRef,
  Renderer2,
  ElementRef,
  AfterViewInit
} from "@angular/core";
import {OneMapService} from "./one-map.service";
import {Subject, of} from "rxjs";
import {takeUntil} from "rxjs/operators";
import {MapUiService} from "./map-ui.service";
import {
  UnifiedMapMode,
  ViewRange,
  UnifiedMapComponent,
  OpenlayersService,
  LayerDataSet
} from "unified-map";
import {NzCascaderOption, NzMessageService} from "ng-zorro-antd";
import {UniversalService} from "src/app/core/util/universal.service";
import {Overlay} from 'ol';
import {ZTList, TypeMapper} from './one-map';
import {Router} from '@angular/router';

@Component({
  selector: "app-one-map",
  templateUrl: "./one-map.component.html",
  styleUrls: ["./one-map.component.scss"]
})
export class OneMapComponent implements OnInit, AfterViewInit {
  @ViewChild("map", {static: true}) unifiedMap: UnifiedMapComponent;
  private unsubscribe: Subject<any> = new Subject();
  private isLastHoverUndefined = true;
  cachePoint: any = {};
  rotation: boolean = false;

  viewRange: ViewRange = [
    [105.008, 36.17],
    [107.372, 39.21]
  ];
  initDataset: { '2d': LayerDataSet; '3d': LayerDataSet } = {
    '2d': 'MapStreets', '3d': 'MapStreets'
  };
  layerDataSet: string = 'MapStreets';
  geoserverUrl = (window as any).environment.geoserverUrl;
  tileServiceUrl: string = (window as any).environment.tileServiceUrl;

  organization: any[] = [
    {
      id: "",
      manageName: "全区"
    }
  ];
  orgSelected: string = "";
  stationId: string = "";
  sectionId: string = "";
  treeNode: any[] = [];
  panelItem: any = {
    stationId: "",
    sectionId: ""
  };
  mode: string = "";
  layerToggle: boolean = false;
  ztActive: number = 0;
  ztList: any[] = ZTList;
  totalSelected: number = 0;
  featureTotal: any = {};
  typeMapper: any = TypeMapper;
  checkAll: boolean = false;
  private deployUrl = (window as any).environment.deployUrl;

  constructor(
    private mapService: OneMapService,
    public mapUiService: MapUiService,
    private viewContainerRef: ViewContainerRef,
    private renderer: Renderer2,
    private elementRef: ElementRef,
    private universalService: UniversalService,
    private olService: OpenlayersService,
    private message: NzMessageService,
    private router: Router
  ) {
  }

  ngOnInit(): void {
    const userInfo = this.universalService.getUserProfile() || {};
    this.stationId =
      userInfo["manageId"] == "10001" ? "" : userInfo["manageId"];
    this.mapUiService.modeChange.subscribe(mode => {
      this.mode = mode;
      // this.ztActive = mode == 'monitor' ? 1 : mode == 'major' ? 2 : 0;
      if (mode === 'monitor') {
        this.ztActive = 1;
      }  else if (mode === 'irrProject') {
        this.ztActive = 2;
      } else if (mode === 'irrInfo') {
        this.ztActive = 3;
      } else {
        this.ztActive = 0;
      }
      this.cachePoint = {};
    });
    this.getOrganization();
    this.regTreeChange();
    this.regPanelChange();
    this.setMapEl();
    this.mapUiService.fTotalChange.subscribe(featureTotal => {
      this.featureTotal = featureTotal;
      this.getSelectedList();
    });
  }

  ngAfterViewInit(): void {
    const twinkleDiv = this.elementRef.nativeElement.querySelector("#scatter-animation");
    this.mapUiService.twinkleOverlay = new Overlay({
      element: twinkleDiv
    });
  }

  setMapEl(): void {
    this.mapUiService.mainCompEl = this.viewContainerRef.element;
  }

  regTreeChange(): void {
    this.mapUiService.treeNodeChange
      .pipe(takeUntil(this.unsubscribe))
      .subscribe(res => {
        this.treeNode = [...res.treeNode];
        if (res.initMap) {
          this.initMap();
          if (this.mapUiService.twinkleOverlay) {
            this.mapUiService.twinkleOverlay.setPosition(null);
          }
        }
      });
  }

  regPanelChange(): void {
    this.mapUiService.panelChange
      .pipe(takeUntil(this.unsubscribe))
      .subscribe(res => {
        this.panelItem = {
          ...res,
          stationId: this.stationId,
          sectionId: this.sectionId
        };
      });
  }

  initMap() {
    this.mapUiService.getMapInstance().then(mapInstance => {
      // this.mapUiService.rotateView(true);
      this.olService.view.on("change:resolution", (e) => {
        if (this.mode != 'major') {
          const layerDataSet = e.target.targetResolution_ < 120 ? 'EsriAerial' : 'MapStreets';
          if (layerDataSet != this.layerDataSet) {
            this.layerDataSet = layerDataSet;
            mapInstance.setBaseLayer({
              url: `${this.tileServiceUrl}imagery/${layerDataSet}/{z}/{x}/{y}`,
              serviceType: 'xyz',
              opacity: 1,
              minimumLevel: 0,
              maximumLevel: 20
            });
          }
        }
      });
      this.mapUiService.olMap.addOverlay(this.mapUiService.twinkleOverlay);
      this.mapUiService.hideAllLayer();
      this.mapUiService.addVectorLayer({
        type: "polygon",
        layerName: "boundary",
        url: "assets/boundary.geojson",
        style: {
          fill: "#000000",
          fillOpacity: 0.1,
          outline: "#ffffff",
          outlineWidth: 1
        },
        visible: true
      });
      this.mapUiService.addVectorLayer({
        type: "polyline",
        layerName: "huanghe0429",
        style: {
          fill: "#a3e4ff",
          fillOpacity: 1,
          outline: "#a3e4ff",
          outlineWidth: 1,
          lineWidth: 3
        },
        visible: true
      });
      this.mapUiService.addVectorLayer({
        type: "polygon",
        layerName: "huanghe",
        style: {
          fill: "#a3e4ff",
          fillOpacity: 0.6,
          outline: "#a3e4ff",
          outlineWidth: 1,
          lineWidth: 3
        },
        visible: true,
        zIndex: 2
      });

      this.updateTreeLayer(true, this.stationId);
    });
  }

  updateTreeLayer(init, stationId?, sectionId?) {
    this.treeNode.map(parent => {
      if (parent.children) {
        parent.children.map(node => {
          if (node.layerName) {
            if (typeof (node.layerName) == 'string') {
              this.addVectorLayer(node, init, stationId, sectionId);
            } else {
              node.layerName.map((item) => {
                this.addVectorLayer(item, init, stationId, sectionId);
              });
            }
          }
        });
      } else if (parent.layerName) {
        this.addVectorLayer(parent, init, stationId, sectionId);
      }
    });
    this.stationId = stationId;
    this.sectionId = sectionId;
  }

  addVectorLayer(node, init, stationId?, sectionId?) {
    if (sectionId && sectionId != this.sectionId) {
      if (node.layerName == "view_zuzhi@2") {
        node.cqlFilter = `id%3D${sectionId}`;
      } else if (node.layerName == "view_guanyu") {
        node.cqlFilter = `station_id%3D${stationId}`;
      } else if (node.layerName != "view_zuzhi@1") {
        node.cqlFilter = `section_id%3D${sectionId}`;
      }
      // this.addVectorLayer(node);
    } else if (init || stationId != this.stationId) {
      if (node.layerName.indexOf("v") == 0) {
        if (node.layerName == "view_zuzhi@1") {
          node.cqlFilter = !stationId
            ? "type%3D1"
            : `id%3D${stationId}`;
        } else if (node.layerName == "view_zuzhi@2") {
          node.cqlFilter = !stationId
            ? "type%3D2"
            : `pid%3D${stationId}`;
        } else {
          const filterName = node.filterName || 'station_id';
          node.cqlFilter = !stationId
            ? ""
            : `${filterName}%3D${stationId}`;
        }
      }
      // this.addVectorLayer(node);
    } else {
      return;
    }
    if (node.type == "point") {
      this.mapUiService.addVectorLayer({
        type: node.type,
        layerName: node.layerName,
        declutter: node.declutter,
        cqlFilter: node.cqlFilter,
        visible: node.checked,
        style: {
          icon: `./assets/images/mapicon/${node.mapicon || node.icon}.png`,
          scale: 0.6
        },
        label: {
          text: "",
          weight: "bold",
          size: 13,
          fill: "#4e5183",
          // fill: node.textColor || "#a6dbf6",
          // outline: "#ffffff",
          // outlineWidth: 1,
          pixelOffset: [0, 12]
        },
        zIndex: node.zIndex || 5
      });
    } else {
      this.mapUiService.addVectorLayer({
        type: node.type,
        layerName: node.layerName,
        cqlFilter: node.cqlFilter,
        visible: node.checked,
        style: {
          fill: node.fillColor,
          fillOpacity: node.fillOpacity || 1,
          outline: node.strokeColor,
          outlineWidth: 1,
          lineWidth: node.width
        },
        label: {
          text: "",
          weight: "bold",
          size: 13,
          fill: node.fillColor || "#ffffff",
          // outline: "#ffffff",
          // outlineWidth: 2,
          pixelOffset: [0, 12]
        },
        zIndex: node.zIndex || 3,
        url: node.url || null
      });
    }
  }

  entityClick(entity: any): void {
    // this.mapUiService.entityClicked.next(event);
    console.log("----------entityClicked-----------");
    if (!entity || !entity.layer || entity.layer == "boundary" || entity.layer == 'huanghe') {
      this.mapUiService.addTwinklePoint(null);
      this.panelItem = {
        ...this.panelItem,
        mode: this.mode
      };
      return;
    }
    const {id, properties = {}, position} = entity;
    const latLon = this.mapUiService.mapInstance.getPositionByEntity(
      entity.layer,
      entity.id
    );
    let layer = entity.layer;
    layer = layer.split("_").pop();

    this.mapUiService.addTwinklePoint(latLon);

    if (layer == 'yjq-video') {
      this.mapUiService.entityClicked.next(entity);
    } else {
      // 显示基本信息
      properties.type = '';
      this.getBaseInfo({
        ...properties,
        latLon,
        position,
        layer
      });
    }
  }

  entityHovered(entity: any): void {
    // console.log(entity);
    if (this.mode == 'major') {
      return;
    }
    if (this.isLastHoverUndefined && entity) {
      this.renderer.setStyle(
        this.mapUiService.mainCompEl.nativeElement,
        "cursor",
        "pointer"
      );
      this.isLastHoverUndefined = false;
    }
    if (!this.isLastHoverUndefined && !entity) {
      this.renderer.setStyle(
        this.mapUiService.mainCompEl.nativeElement,
        "cursor",
        "default"
      );
      this.isLastHoverUndefined = true;
    }
    if (!entity) {
      return;
    } else if (!entity.properties.type || entity.properties.type == 'polygon') {
      return;
    }

    const {layer, id, properties = {}} = entity;
    if (layer && layer != "boundary") {
      const defTxt = "";
      const hoverTxt =
        properties.name ||
        properties["名称"] ||
        properties["NAME"] ||
        properties["GYMC"] ||
        properties['Stadia_Name'] ||
        properties['wiust_nm'] ||
        properties['MC'] ||
        properties['JZWMC'] ||
        properties['objectName'] ||
        properties['objname'];
      if (this.cachePoint.id && this.cachePoint.id !== id) {
        if (this.cachePoint.layer == 'ganqu-yjq') {
          this.mapUiService.updatePolylineEntity(this.cachePoint.layer, this.cachePoint.id, {
            style: {
              lineWidth: 5
            }
          }, {text: defTxt});
        } else {
          this.mapUiService.updatePointEntity(
            this.cachePoint.layer,
            this.cachePoint.id,
            {},
            {text: defTxt}
          );
        }
      }
      this.cachePoint = {
        layer,
        id,
        properties
      };
      if (layer == 'ganqu-yjq') {
        this.mapUiService.updatePolylineEntity(layer, id, {
          style: {
            lineWidth: 9
          }
        }, {
          text: hoverTxt
        });
      } else {
        this.mapUiService.updatePointEntity(
          layer,
          id,
          {},
          {
            text: hoverTxt
          }
        );
      }
    }
  }

  mapInitialized(initMode: UnifiedMapMode): void {
    this.mapUiService.mapInitialized.next(initMode);
  }

  onCheckAll() {
    console.log(this.checkAll);
    this.treeNode.map(p => {
      p.checked = this.checkAll;
      if (p.children) {
        p.children.map(c => {
          if (c.children) {
            c.children.map(node => {
              node.checked = this.checkAll;
              this.mapUiService.selectNode(this.treeNode, node);
            });
          } else {
            c.checked = this.checkAll;
            this.mapUiService.selectNode(this.treeNode, c);
          }
        });
      } else {
        this.mapUiService.selectNode(this.treeNode, p);
      }
    });
    this.treeNode = [...this.treeNode];
    this.getSelectedList();
  }

  onNodeSelected(data) {
    this.mapUiService.selectNode(this.treeNode, data);
    this.panelItem = {
      ...data,
      mode: this.mode
    };
    this.mapUiService.panelChange.next(this.panelItem);
    this.mapUiService.nodeSelectChange.next(data);
    this.getSelectedList();
  }

  getSelectedList() {
    const selectedList = [];
    let totalSelected = 0;
    this.treeNode.map((item) => {
      if (item.children) {
        item.children.map(node => {
          if (node.checked && node.type == 'point' && this.featureTotal[node.layerName]) {
            const total = this.featureTotal[node.layerName];
            selectedList.push({
              ...node,
              total
            });
            totalSelected += total;
          }
        });
      } else if (item.isLeaf) {
        if (item.checked && item.type == 'point' && this.featureTotal[item.layerName]) {
          const total = this.featureTotal[item.layerName];
          selectedList.push({
            ...item,
            total
          });
          totalSelected += total;
        }
      }
    });
    this.totalSelected = totalSelected;
    this.mapUiService.selectChange.next(selectedList);
  }

  validate(option: NzCascaderOption, index: number): boolean {
    return true;
  }

  onChangeOrg(values: string[]): void {
    // console.log(values);
    let stationId;
    let sectionId;
    if (values.length == 1) {
      stationId = values[0];
    } else if (values.length == 2) {
      stationId = values[1];
    } else if (values.length == 3) {
      stationId = values[1];
      sectionId = values[2];
    }
    this.updateTreeLayer(false, stationId, sectionId);
    this.panelItem = {
      ...this.panelItem,
      stationId,
      sectionId
    };
  }

  onChangeRegion(values: string[]): void {
    let code;
    if (values.length == 1) {
      this.mapUiService.mapInstance.updateVectorLayer("County", {
        visible: false
      });
      this.mapUiService.mapInstance.updateVectorLayer("boundary", {
        visible: true
      });
      setTimeout(() => {
        this.mapUiService.initViewRange("boundary");
      }, 600);
    } else if (values.length == 2) {
    } else {
      code = values.pop();
      this.mapUiService.addVectorLayer({
        url: `${this.geoserverUrl}nxszy/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=nxszy%3ACounty&outputFormat=application%2Fjson&cql_filter=Code%3D${code}000`,
        type: "polygon",
        layerName: "County",
        visible: true,
        style: {
          fill: "#000000",
          fillOpacity: 0.5,
          outline: "#ffffff",
          outlineWidth: 1
        },
        label: {
          text: "",
          weight: "bold",
          size: 13,
          fill: "#88abda",
          outline: "#ffffff",
          outlineWidth: 2,
          pixelOffset: [0, 12]
        },
        zIndex: 2
      });
      setTimeout(() => {
        this.mapUiService.initViewRange("County");
      }, 600);
    }
  }

  getOrganization() {
    this.mapService
      .queryOffice({
        type: 1,
        id: this.stationId,
        pageSize: 100
      })
      .subscribe(res => {
        // console.log(res);
        const offices = res["list"];
        const orgChange: Subject<any> = new Subject();
        orgChange.subscribe(data => {
          if (this.stationId) {
            this.organization = data;
          } else {
            this.organization[0].children = data;
          }
          // console.log(this.organization);
        });
        offices.map((item, i) => {
          this.mapService
            .queryOffice({
              type: 2,
              pid: item.id
            })
            .subscribe(r => {
              item.children = r["list"].map(c => {
                c.isLeaf = true;
                return c;
              });
              if (i == offices.length - 1) {
                orgChange.next(offices);
              }
            });
        });
      });
  }

  onSearchSelect(item) {
    console.log(item);
    item.layer = this.typeMapper[item.type];
    this.getBaseInfo(item, true);
    let selectNode;
    this.treeNode.map(parent => {
      if (parent.children) {
        parent.children.map(node => {
          if (node.children) {
            node.children.map(child => {
              const layerStr = typeof (child.layerName) == 'string' && child.layerName.split('_') || [];
              if (layerStr.indexOf(item.layer) >= 0) {
                child.checked = true;
                selectNode = child;
                if (item.geom) {
                  const pointPosition = this.mapUiService.transformCoordinate([item.geom.lng, item.geom.lat]);
                  this.mapUiService.twinkleOverlay.setPosition(pointPosition);
                  this.mapUiService.showTwinkle = true;
                }
              }
            });
          } else {
            const layerStr = typeof (node.layerName) == 'string' && node.layerName.split('_') || [];
            if (layerStr.indexOf(item.layer) >= 0) {
              node.checked = true;
              selectNode = node;
              if (item.geom) {
                const pointPosition = this.mapUiService.transformCoordinate([item.geom.lng, item.geom.lat]);
                this.mapUiService.twinkleOverlay.setPosition(pointPosition);
                this.mapUiService.showTwinkle = true;
              }
            }
          }
        });
      }
    });
    this.treeNode = [...this.treeNode];
    this.mapUiService.selectNode(this.treeNode, selectNode);
    this.getSelectedList();
    // this.mapUiService.searchSelected.next(item);
  }

  onBuildingSelect(item) {
    // console.log(item);
    if (item.geom) {
      const pointPosition = this.mapUiService.transformCoordinate([item.geom.lng, item.geom.lat]);
      this.mapUiService.twinkleOverlay.setPosition(pointPosition);
      this.mapUiService.showTwinkle = true;
      this.mapUiService.flyToPoint([item.geom.lng, item.geom.lat], false, this.mapUiService.currentZoom);
      this.getBaseInfo(item);
    }
  }

  setRotation() {
    this.rotation = !this.rotation;
    this.mapUiService.rotateView(this.rotation);
  }

  onActiveZT(idx) {
    if (ZTList[idx].routePath) {
      this.ztActive = idx;
      this.router.navigate([ZTList[idx].routePath]);
    } else if (ZTList[idx].url) {
      window.open(`${this.deployUrl}${ZTList[idx].url}`);
    } else {
      this.message.warning("正在开发中");
    }
  }

  getBaseInfo(item, flyto?) {
    let queryObs;
    switch (item.layer) {
      case 'guanyu':
      case 'irrArea':
        queryObs = this.mapService.queryIrrArea({
          name: item.name || item.buildName
        });
        break;
      case 'zuzhi@1':
      case 'zuzhi@2':
        queryObs = this.mapService.queryOffice({
          manageCode: item.code || item.buildCode
        });
        break;
      case 'bengzhan':
      case 'bengzhan2':
      case 'zybz':
        queryObs = this.mapService.queryBengzhan({
          pumpCode: item.code || item.buildCode || item.Pump_Code || item.pumpCode
        });
        break;
      case 'paishuigou':
        queryObs = this.mapService.queryPaishuigou({
          drainageCode: item['编码'] || item.buildCode
        });
        break;
      case 'qiaoliang':
        queryObs = this.mapService.queryBridge({
          bridgeCode: item.code || item.buildCode
        });
        break;
      case 'yiliuyan':
        queryObs = this.mapService.queryYiliuyan({
          code: item.code || item.buildCode
        });
        break;
      case 'ganqu-yjq':
        queryObs = this.mapService.queryCanal({
          canalName: item.NAME || item.buildName || item.canalName || item.Name
        });
        break;
      case 'handong':
        queryObs = this.mapService.queryHandong({
          culvertCode: item.code,
          culvertName: item.name,
          stationId: item.station_id,
          sectionId: item.section_id
        });
        break;
      case 'ducao':
        queryObs = this.mapService.queryDucao({
          flumeName: item.name || item.buildName
        });
        break;
      case 'jinshuizha':
      case 'tuishuizha':
      case 'jiezhizha':
      case 'zyzm':
        queryObs = this.mapService.queryGate({
          strobeCode: item.code || item.buildCode || item.Strobe_Code || item.strobeCode
        });
        break;
      case 'dieshui':
        queryObs = this.mapService.queryDieshui({
          dropCode: item.code || item.buildCode
        });
        break;
      case 'zhikaikou':
        queryObs = this.mapService.queryZhikaikou({
          watergateCode: item.name || item.buildName
        });
        break;
      case 'zhihongqu':
        queryObs = this.mapService.queryZhihongqu({
          detentionName: item.name || item.buildName
        });
        break;
      case 'shanhonggou':
        queryObs = this.mapService.queryShanhonggou({
          floodName: item.name || item.buildName
        });
        break;
      case 'gyysdw':
        queryObs = this.mapService.queryGyysdw({
          name: item.name || item.buildName
        });
        break;
      case 'hd': // 河道水文站
      case 'yz': // 堰闸水文站
      case 'hh': // 黄河断面
      case 'skswz': // 水库水文站
      case 'gqdm': // 干渠断面
      case 'zygq': // 干渠断面
      case 'shg': // 山洪沟断面
      case 'psg': // 排水沟断面
      case 'zypsg': // 排水沟断面
      case 'ylz': // 雨量站
      case 'cyylz': // 常用雨量站
      case 'sqz': // 墒情站
        if (item.pumpCode || item.Pump_Code) {
          item.layer = 'zybz';
          queryObs = this.mapService.queryBengzhan({
            pumpCode: item.pumpCode || item.Pump_Code
          });
        } else {
          queryObs = this.mapService.getSectionInfo(item.Stadia_Code || item.buildCode || item.stcd || item.stadiaCode);
        }
        break;
      case 'db': // 地表取水口
      case 'dx': // 地下取水口
      case 'gy': // 工业取水口
      case 'ny': // 农业取水口
      case 'sh': // 生活取水口
        queryObs = this.mapService.getIntakeInfo(item.wiust_cd || item.wiu_cd || item.buildCode || item.wiustCd);
        break;
      case 'gyjc': // 工业取水口
      case 'nyjc': // 农业取水口
      case 'shjc': // 生活取水口
      case 'hhjc': // 混合取水口
        queryObs = this.mapService.getIntakeInfo2(item.wiu_cd || item.wiuCd);
        break;
      case 'zlqsk':
        queryObs = this.mapService.getInfoZQSK(item.ID || item.id || item.buildCode);
        break;
      case 'qdlqsk':
        queryObs = this.mapService.getInfoQDQSK(item.ID || item.id || item.buildCode);
        break;
      case 'bzlqsk':
        queryObs = this.mapService.getInfoBZQSK(item.ID || item.id || item.buildCode);
        break;
      case 'sjlqsk':
        queryObs = this.mapService.getInfoSJQSK(item.ID || item.id || item.buildCode);
        break;
      case 'blqsk':
        queryObs = this.mapService.getInfoBQSK(item.ID || item.id || item.buildCode);
        break;
      case 'sdzlqsk':
        queryObs = this.mapService.getInfoSDZQSK(item.ID || item.id || item.buildCode);
        break;
      case 'qtlqsk':
        queryObs = this.mapService.getInfoQTQSK(item.ID || item.id || item.buildCode);
        break;
      default:
        queryObs = of({});
        break;
    }
    queryObs.subscribe(res => {
      // console.log(res);
      if (res["list"] && res["list"].length) {
        this.panelItem = {
          layerName: this.panelItem.layerName,
          mode: 'info',
          infoData: {
            ...item,
            // ...res["list"][0]
          }
        };
      } else {
        this.panelItem = {
          layerName: this.panelItem.layerName,
          mode: 'info',
          infoData: {
            ...item,
            ...res
          }
        };
      }
      if (flyto && item.geom) {
        this.mapUiService.flyToPoint([item.geom.lng, item.geom.lat], false, this.mapUiService.currentZoom);
      }
    });
  }
}
